/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tos.dekker;

import java.util.Random;
import org.jdesktop.application.FrameView;
import tos.TosView;

/**
 *
 * @author Milos
 */
public class Processes extends Thread {
    // promenljive za kontrolu

    private Variables variables;
    // Deljena promenjiva koja se povecava
    private Brojac counter;
    // promenljiva koja pokazuje koliko puta treba povecati brojac
    int noOfIncrements;
    // random broj
    private Random r;
    // seed random broj
    private long seed;
    // identifikacioni broj procesa
    private int processID;
    
    // Parent frame for this process.
    private FrameView parent;

    // Konstruktor
    public Processes(Variables variables, int processID, Brojac counter, int noOfIncrements, FrameView parent) {
        this.variables = variables;
        this.processID = processID;
        this.counter = counter;
        this.noOfIncrements = noOfIncrements;
        this.parent = parent;
        Random temp = new Random();
        seed = temp.nextLong();
        r = new Random(seed);
    }

    // Metada koja uspavljuje nit na slucajan broj milisekundi izmedju 0 i 1000
    public void busy() {
        //int pause = (int) (r.nextDouble() * 1000);

//        try {
//            sleep(pause);
//        } catch (InterruptedException ex) {
//            System.out.println("Erorr!!" + ex.toString());
//        }
    }

    // Metoda koja odredjuje identifikacioni broj drugog procesa
    public int anotherProcessID(int processID) {
        if (processID == 0) {
            return 1;
        } else {
            return 0;
        }
    }

    // Metoda koja opisuje ne kriticnu sekciju
    public void nonCritical() {
        System.out.println("Proces p" + processID + " ulazi u nekriticnu sekciju.");
        busy();
        System.out.println("Proces p" + processID + " izlazi iz nekriticne sekcije.");
    }

    // Metoda koja opisuje rutine pre ulaska u kriticnu sekciju
    public void preCritical() {
        variables.setWant(processID, true);
        while (variables.getWant(anotherProcessID(processID))) {
            if (variables.getTurn() != processID) {
                variables.setWant(processID, false);
                while (variables.getTurn() != processID);
                variables.setWant(processID, true);
            }
        }
    }

    // Metoda koja opisuje rutine posle ulaska u kriticnu sekciju
    public void postCritical() {
        variables.setTurn(anotherProcessID(processID));
        variables.setWant(processID, false);
    }

    // Metoda koja opisuje kriticnu sekciju
    public void critical() {
        System.out.println("Proces p" + processID + " ulazi u kriticnu sekciju.");
        ((TosView)parent).appendOutput("Proces p" + processID + " ulazi u kriticnu sekciju.\n");
        busy();
        int temp = counter.getBroj();
        temp++;
        counter.setBroj(temp);
        System.out.println("Proces p" + processID + " izlazi iz kriticne sekcije.");
        ((TosView)parent).appendOutput("Proces p" + processID + " izlazi iz kriticne sekcije.\n");
    }

    // Run metoda
    @Override
    public void run() {
        for (int i = 0; i < noOfIncrements; i++) {
            nonCritical();
            preCritical();
            critical();
            postCritical();
        }
    }
}
